/*
** $Id: lfunc.h,v 2.15.1.1 2017/04/19 17:39:34 roberto Exp $
** Auxiliary functions to manipulate prototypes and closures
** See Copyright Notice in lua.h
*/

#ifndef lfunc_h
#define lfunc_h


#include "lobject.h"


#define sizeCclosure(n)  (cast(int, sizeof(CClosure)) + \
                         cast(int, sizeof(TValue)*((n)-1)))

#define sizeLclosure(n)  (cast(int, sizeof(LClosure)) + \
                         cast(int, sizeof(TValue *)*((n)-1)))


/* test whether thread is in 'twups' list */
#define isintwups(L)  (L->twups != L)


/*
** maximum number of upvalues in a closure (both C and Lua). (Value
** must fit in a VM register.)
*/
#define MAXUPVAL  255

/**
 * Lua闭包的上值（Upvalue）结构体。
 *
 * 上值是Lua闭包中引用的外部局部变量，可以是开放的（指向栈）或关闭的（拥有自己的值）。
 *
 * @field v 指向栈上的值或自身的值。
 * @field refcount 引用计数器，用于管理上值的生命周期。
 * @field u 联合体，表示上值的状态：
 *   - open: 当上值为开放状态时，包含指向下一个上值的指针和标记位（避免死线程循环）。
 *   - value: 当上值为关闭状态时，存储具体的值。
 */
/*
** Upvalues for Lua closures
*/
struct UpVal {
    TValue *v;  /* points to stack or to its own value */
    lu_mem refcount;  /* reference counter */
    union {
        struct {  /* (when open) */
            UpVal *next;  /* linked list */
            int touched;  /* mark to avoid cycles with dead threads */
        } open;
        TValue value;  /* the value (when closed) */
    } u;
};

/**
 * 检查用户指针（up）是否处于打开状态。
 *
 * @param up 用户指针，指向一个结构体。
 * @return 返回布尔值，true 表示用户指针处于打开状态，false 表示未打开。
 *
 * @note 该宏通过检查用户指针的 `v` 成员是否指向其自身的 `u.value` 来判断状态。
 */
#define upisopen(up) ((up)->v != &(up)->u.value)

LUAI_FUNC Proto *luaF_newproto(lua_State *L);

LUAI_FUNC CClosure *luaF_newCclosure(lua_State *L, int nelems);

LUAI_FUNC LClosure *luaF_newLclosure(lua_State *L, int nelems);

LUAI_FUNC void luaF_initupvals(lua_State *L, LClosure *cl);

LUAI_FUNC UpVal *luaF_findupval(lua_State *L, StkId level);

LUAI_FUNC void luaF_close(lua_State *L, StkId level);

LUAI_FUNC void luaF_freeproto(lua_State *L, Proto *f);

LUAI_FUNC const char *luaF_getlocalname(const Proto *func, int local_number,
                                        int pc);


#endif
